We've talked about how everyting in Python is an object. In addition, we've come to use many objects. However, we have not created any objects. In this lecture, we will discuss object-oriented programming, and what we can achieve with it. Here is what we will cover:
1. Classes
> Attributes
2. Methods
3. Inheritance
Let's take a look at the building block of creating an object - a class!
The fundamental building block of an object, is the class. A class defines all of the specifications of an object, from its attributes, methods, and more. The declaration of a class begins with the "class" keyword.
class Name(superclass):
// etc
We'll talk later about what superclass means. However, this is the opening statement for a class. Here's another example:
In [6]:
# Creating a class called Bike
class Bike:
pass
If you do not already know, the word "instantiation" means to create a version of an object. Here is how we would instantiate a bike.
In [4]:
# An 'instance' of a bike
my_bike = Bike()
type(my_bike)
Out[4]:
Now, my_bike is an object reference to "Bike". This means that the variable doesn't actually hold the object in memory, but simply points to it.
To give objects attributes (i.e. a bike's wheel size, speed, weight), you need to create the
__init__(attributes...)
function. This function is called whenever an object is instantiated. It's what assigns the values you want on an object. Let's see its use below.
In [7]:
class Bike:
def __init__(self, speed, wheel, weight):
self.speed = speed
self.wheel = wheel
self.weight = weight
What just happened? We created the init method in Bike, and provided it four parameters: self, speed, wheel, and weight. In the body of the method, we assigned self.attr to the attribute. First, let's discuss the self. The word self is actually not a keyword, but a type of requirement from Python. You see, all Python methods must have a reference to the object itself. You can use any name you like for that reference, but everyone uses the word "self" because it is simply convention.
The attributes in this class are speed, wheel, and weight. In the method body, we set the referenced object's attribute value to... well... itself (or, in other words, whatever was sent in). Let's try an instantiation below.
In [12]:
# Instantiating a Bike Object
woo = Bike(2, 4, 5)
The instantiation checks out. Here's what happened:
self.speed = 2
self.wheel = 4
self.weight = 5
This allows us to use dot notation to access the properties. How do we get the wheel size of the bike? We use the following notation:
object.attr
It's that simple.
In [13]:
woo.speed
Out[13]:
In [14]:
woo.wheel
Out[14]:
In [15]:
woo.weight
Out[15]:
We've discussed functions numerous amounts of times, and methods are essentially the same thing but written inside of functions. We can use attribute values now, instead.
In [27]:
class Bike:
# __init__() function
def __init__(self, speed, wheel, weight):
self.speed = speed
self.wheel = wheel
self.weight = weight
# A method calculates the max weight of a person on the bike
def max_weight(self, rider_weight):
max_weight = rider_weight * self.weight
return max_weight
# Another method
def some_method(self):
pass
In [28]:
woo = Bike(2, 4, 5)
In [29]:
woo.max_weight(30)
Out[29]:
There are a few methods in Python that you can alter in your class referred to as "special methods". These methods allow you to control certain behaviors that happen behind the scenes in your program. Things like printing your object, or how it reacts to operators, etc can be controlled via these methods. Let's look at a few.
In [30]:
class Bike():
def __init__(self, speed, wheel, weight):
self.speed = speed
self.wheel = wheel
self.weight = weight
def __str__(self):
return "Bike Speed: {} Wheel Size: {} Weight: {}".format(self.speed, self.wheel, self.weight)
In [31]:
woo = Bike(3, 4, 5)
In [32]:
print(woo)